unit GrfObject;

interface

  uses
    grf, grftypes, grfsupport;

  type
    TGrfObject = class
      private
        fGrf : PGrf;
        fGrfError : TGrfError;
      public
        constructor Create(Path : AnsiString);
        destructor Destroy(); override;
        function FileExists(Filename : TGrfFilename) : Boolean;
        function Merge(var ChildGrfObject : TGrfObject): Boolean;
        procedure Save();
        property Grf : PGrf read fGrf;
    end;

  const
    GRF_ERROR_OPEN_FAILURE = 'Failed to open GRF';

  function GrfOpenCallback(filename: PGrfFile; error: PGrfError) : Integer; cdecl;

implementation

  uses SysUtils, Dialogs, StringUtils;

  function GrfOpenCallback(filename: PGrfFile; error: PGrfError) : Integer;
  begin
    //test
    result := 1;
  end;

  constructor TGrfObject.Create(Path : AnsiString);
  begin
    //AnsiPath := Path;
    fGrf := grf_callback_open(PAnsiChar(Path), 'r+b', fGrfError, nil);
    if fGrf = nil then raise Exception.Create(GRF_ERROR_OPEN_FAILURE);
  end;

  destructor TGrfObject.Destroy();
  begin
    grf_free(fGrf);
  end;

  function TGrfObject.FileExists(Filename: TGrfFilename) : Boolean;
  var
    i : Cardinal;
  begin
    Result := false;
    for i := 0 to fGrf.nfiles - 1 do
    begin
      if fGrf.files[i].name = Filename then Result := true;
      break;
    end;
  end;

  function FlushCallback(grffile : PGrfFile; error : PGrfError) : Integer; cdecl;
  begin
    Result := 0;
  end;

  function TGrfObject.Merge(var ChildGrfObject: TGrfObject) : Boolean;
  var
    //Iterator
    i : Cardinal;
    //Data info
    DataBuffer : Pointer;
    Size : Cardinal;
    //Error struct
    Error : TGrfError;
  begin
    Result := false;
    if (fGrf <> nil) and (ChildGrfObject.Grf <> nil) then
    begin
      for i := 0 to ChildGrfObject.Grf.nfiles - 1 do
      begin
        //Check if the current iteration is a directory or file
        if GRFFILE_IS_DIR(ChildGrfObject.Grf.files[i]) = false then
        begin
          //Grab the file by index
          DataBuffer := grf_index_get(
            ChildGrfObject.Grf,
            i,
            Size,
            Error
          );
          //Add/replace file in parent Grf
          grf_put(
            fGrf,
            ChildGrfObject.Grf.files[i].name,
            DataBuffer,
            Size,
            GRFFILE_FLAG_FILE,
            Error
          );
        end;
      end;
    end;
  end;

  procedure TGrfObject.Save();
  var
    Error : TGrfError;
  begin
    grf_callback_flush(fGrf, Error, FlushCallback);
  end;

end.
